package com.swak.persistence.datasource;

import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;

import com.swak.annotation.DynamicSource;
import com.swak.utils.StringUtils;

/**
 * 这个动态数据源的切换是一个鸡肋；
 * 
 * 如果真的有多个数据源，应该在Service层面做隔离， 通过 Aspect 来做事务的注入，
 * 见 MultipleDbConfig；
 * 
 * 如果仅仅是主从数据源，也只是需要 MsingFilter 即可；
 * 
 * DynamicDataSourceAspect 实际上没有使用场景；
 * 
 * @author lifeng
 */
@Aspect
public class DynamicDataSourceAspect implements Ordered {

	private Logger log = LoggerFactory.getLogger(this.getClass());

	/**
	 * 定义切入点
	 */
	@Pointcut(value = "@annotation(com.swak.annotation.DynamicSource)")
	private void DynamicDataSourceAspect_cut() {
	}

	@Around("DynamicDataSourceAspect_cut()")
	public Object around(ProceedingJoinPoint point) throws Throwable {
		DynamicSource datasource = this.getMethod(point).getAnnotation(DynamicSource.class);
		if (!(datasource != null && StringUtils.isNotBlank(datasource.value()))) {
			return point.proceed();
		}

		if (log.isDebugEnabled()) {
			log.debug("设置数据源为：" + datasource.value());
		}
		DataSourceHolder.setDataSourceType(datasource.value());
		try {
			return point.proceed();
		} finally {
			if (log.isDebugEnabled()) {
				log.debug("清空数据源信息！");
			}
			DataSourceHolder.clearDataSourceType();
		}
	}

	/**
	 * 获得当前的 Method
	 * 
	 * @param point
	 * @return
	 */
	private Method getMethod(ProceedingJoinPoint point) {
		Signature s = point.getSignature();
		MethodSignature ms = (MethodSignature) s;
		return ms.getMethod();
	}

	/**
	 * Aop的顺序要早于spring的事务
	 */
	@Override
	public int getOrder() {
		return Ordered.HIGHEST_PRECEDENCE;
	}
}